import 'dart:developer';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:rxdart/rxdart.dart';
import 'user_repo.dart';
import '../models/models.dart';
import '../entities/entities.dart';


class FirebaseUserRepo implements UserRepository {
  final FirebaseAuth _firebaseAuth;
	final usersCollection = FirebaseFirestore.instance.collection('users');

  FirebaseUserRepo({
    FirebaseAuth? firebaseAuth,
  }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;

  @override
  Stream<MyUser?> get user {
    return _firebaseAuth.authStateChanges().flatMap((firebaseUser) async* {
      if(firebaseUser == null) {
        yield MyUser.empty;
      } else {
        yield await usersCollection
          .doc(firebaseUser.uid)
          .get()
          .then((value) => MyUser.fromEntity(MyUserEntity.fromDocument(value.data()!)));
      }
    });
  }

  @override
  Future<void> signIn(String email, String password) async {
    try {
      await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
    } catch (e) {
      log(e.toString());
      rethrow;
    }
  }

  @override
  Future<MyUser> signUp(MyUser myUser, String password) async {
    try {
      UserCredential user = await _firebaseAuth.createUserWithEmailAndPassword(
        email: myUser.email, 
        password: password
      );

      myUser.userId = user.user!.uid;
      return myUser;
    } catch (e) {
      log(e.toString());
      rethrow;
    }
  }

  @override
  Future<void> logOut() async {
    await _firebaseAuth.signOut();
  }

  @override
  Future<void> setUserData(MyUser myUser) async {
    try {
      await usersCollection
        .doc(myUser.userId)
        .set(myUser.toEntity().toDocument());
    } catch (e) {
      log(e.toString());
      rethrow;
    }
  }
  
  @override
  Future<MyUser> getUser(String userId) async {
    try {
      return await usersCollection
        .doc(userId)
          .get()
          .then((value) => MyUser.fromEntity(MyUserEntity.fromDocument(value.data()!)));
    } catch (e) {
      log(e.toString());
      rethrow;
    }
  }
  
  @override
  Future<void> followUser(String followeeId) async {
    final follower= await getCorrentUser();
    final followeeRef = usersCollection.doc(followeeId);
    final followerRef = usersCollection.doc(follower.userId);
    try {
      await followeeRef.update({
      'followers': FieldValue.arrayUnion([follower.userId]), // 添加新值
    });
      await followerRef.update({
      'following': FieldValue.arrayUnion([followeeId]), // 添加新值
    });
    } catch (e) {
      log(e.toString());
      rethrow;
    }
    
  }
  
 
  
  @override
  Future<void> unFollowUser(String followeeId) async {
    final follower= await getCorrentUser();
    final followeeRef = usersCollection.doc(followeeId);
    final followerRef = usersCollection.doc(follower.userId);
    try {
      await followeeRef.update({
      'followers': FieldValue.arrayRemove([follower.userId]), // 添加新值
    });
      await followerRef.update({
      'following': FieldValue.arrayRemove([followeeId]), // 添加新值
    });
    } catch (e) {
      log(e.toString());
      rethrow;
    }
  }
  
  @override
  Future<MyUser> getCorrentUser() async {
    final user= FirebaseAuth.instance.currentUser;
    var usedID=user?.uid;
    try{
      return await getUser(usedID!);
    }catch(e){
      throw Exception('An async error occurred!');
    }
  }

}
  
  // @override
  // Future<void> unFollowUser(String userId) {
  //   // TODO: implement unFollowUser
  //   throw UnimplementedError();
  // }
  
  
  
  

  

  
  
